package com.lai.hospital.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aliyun.ocr_api20210707.models.RecognizeIdcardResponseBody;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lai.hospital.config.OCRConfig;
import com.lai.hospital.constant.CommonConst;
import com.lai.hospital.dao.AppointmentDao;
import com.lai.hospital.dao.DoctorDao;
import com.lai.hospital.dao.PatientDao;
import com.lai.hospital.dao.UserPatientDao;
import com.lai.hospital.dto.DoctorScheduleDTO;
import com.lai.hospital.dto.UserPatientDTO;
import com.lai.hospital.entity.Appointment;
import com.lai.hospital.entity.Doctor;
import com.lai.hospital.entity.Patient;
import com.lai.hospital.entity.UserPatient;
import com.lai.hospital.enums.FilePathEnum;
import com.lai.hospital.exception.BizException;
import com.lai.hospital.service.PatientService;
import com.lai.hospital.service.UserPatientService;
import com.lai.hospital.strategy.context.UploadStrategyContext;
import com.lai.hospital.utils.BeanCopyUtils;
import com.lai.hospital.utils.PageUtils;
import com.lai.hospital.utils.UserUtils;
import com.lai.hospital.vo.ConditionVO;
import com.lai.hospital.vo.PageResult;
import com.lai.hospital.vo.PatientBaseInfoVO;
import com.lai.hospital.vo.UserPatientVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : lai
 * @version V1.0
 * @Project: hospital-springboot
 * @Package com.lai.hospital.service.impl
 * @Description: 患者服务
 * @date Date : 2022年11月27日 23:44
 */
@Service
public class PatientServiceImpl extends ServiceImpl<PatientDao, Patient> implements PatientService {

    @Autowired
    private PatientDao patientDao;

    @Autowired
    private UserPatientService userPatientService;
    @Autowired
    private UserPatientDao userPatientDao;

    @Autowired
    private UploadStrategyContext uploadStrategyContext;
    @Autowired
    private OCRConfig ocrConfig;

    @Autowired
    private DoctorDao doctorDao;

    @Autowired
    private AppointmentDao appointmentDao;

    @Override
    public PageResult<Patient> listPatient(ConditionVO conditionVO) {
        Integer count;
        Page<Patient> page = new Page<>(PageUtils.getCurrent(), PageUtils.getSize());
        PageResult<Patient> pageResult = new PageResult<>();
        //分页查询
        Page<Patient> patientPage = patientDao.selectPage(page, new LambdaQueryWrapper<Patient>()
                .like(StringUtils.isNotBlank(conditionVO.getKeywords()), Patient::getPatientName, conditionVO.getKeywords())
                .eq(Objects.nonNull(conditionVO.getSex()), Patient::getSex, conditionVO.getSex())
                .orderByAsc(Patient::getId));
        pageResult.setRecordList(BeanCopyUtils.copyList(patientPage.getRecords(), Patient.class));
        //设置总数
        if (StringUtils.isNotBlank(conditionVO.getKeywords()) || Objects.nonNull(conditionVO.getSex())) {
            //当为条件查询时
            pageResult.setCount(patientPage.getRecords().size());
        } else {
            //无条件查询
            pageResult.setCount(patientDao.selectCount(null));
        }
        return pageResult;
    }

    @Override
    public void deletePatient(Integer id) {
        patientDao.deleteById(id);
    }

    @Override
    public Patient getPatientById(Integer id) {
        return patientDao.selectById(id);
    }

    @Override
    public void saveOrUpdatePatient(PatientBaseInfoVO patientBaseInfoVO) {

        if(!IdcardUtil.isValidCard(patientBaseInfoVO.getIdNumber())){
            throw new BizException("身份证号不正确");
        }
        // 保存或修改就诊人信息
        Patient patient = BeanCopyUtils.copyObject(patientBaseInfoVO, Patient.class);
        //根据身份证号设置年龄和性别
        patient.setAge(IdcardUtil.getAgeByIdCard(patientBaseInfoVO.getIdNumber()));
        patient.setSex(IdcardUtil.getGenderByIdCard(patientBaseInfoVO.getIdNumber()));
        this.saveOrUpdate(patient);
        //查询这个用户下有没有就诊人
        UserPatient isUserPatient = userPatientDao.selectOne(new LambdaQueryWrapper<UserPatient>()
                .eq(UserPatient::getUserId, UserUtils.getLoginUser().getUserInfoId()));
        UserPatient userPatient;
        if(Objects.isNull(isUserPatient)){//如果没有 就诊人  说明此时添加的就是第一个  是否默认设置为true
            userPatient = UserPatient.builder()
                    .patientId(patient.getId())
                    .userId(UserUtils.getLoginUser().getUserInfoId())
                    .relation(patientBaseInfoVO.getRelation())
                    .is_default(CommonConst.TRUE)
                    .build();
        }else{
            userPatient = UserPatient.builder()
                    .patientId(patient.getId())
                    .userId(UserUtils.getLoginUser().getUserInfoId())
                    .relation(patientBaseInfoVO.getRelation())
                    .is_default(CommonConst.FALSE)
                    .build();
        }
        // 保存或修改用户与就诊人关系
        userPatientService.saveOrUpdate(userPatient);
    }

    @Override
    public List<UserPatientDTO> listPatientByUserId(Integer userId) {
        //1、查询此用户下有多少个就诊人
        return patientDao.listPatientByUserId(userId);
        /*return patientDao.listPatientByUserId(userId).stream().map( item -> {
            String idNumberChar = item.getIdNumber();
            for(int i = 0; i < item.getIdNumber().length(); i++){
                if(i > 2 || i < 14){
                    idNumberChar[i] = '*';
                }
            }
            item.setIdNumber(idNumberChar.toString());
            return item;
        }).collect(Collectors.toList());*/

    }

    @Override
    public void deleteUserPatient(Integer userPatientId) {
        userPatientDao.deleteById(userPatientId);
    }

    @Override
    public void updateUserPatientRelation(UserPatientVO userPatientVO) {
        UserPatient userPatient = BeanCopyUtils.copyObject(userPatientVO, UserPatient.class);
        userPatientDao.updateById(userPatient);
    }

    @Override
    public Patient getUserDefaultPatient() {
        UserPatient userPatient = userPatientDao.selectOne(new LambdaQueryWrapper<UserPatient>()
                .eq(UserPatient::getUserId, UserUtils.getLoginUser().getUserInfoId())
                .eq(UserPatient::getIs_default, CommonConst.TRUE));
        Patient patient = patientDao.selectById(userPatient.getPatientId());
        return patient;
    }

    @Override
    public RecognizeIdcardResponseBody OCR(MultipartFile file) throws Exception {
        RecognizeIdcardResponseBody recognizeIdcardResponseBody = ocrConfig.OCR(file);
        return recognizeIdcardResponseBody;
    }

    @Override
    public PageResult<Patient> listMyPatient(ConditionVO conditionVO) {
        Integer count;
        PageResult pageResult = new PageResult<>();
        //1、查询 预约表中的所有doctorId等于 doctorid的
        Doctor doctor = doctorDao.selectOne(new LambdaQueryWrapper<Doctor>()
                .eq(Doctor::getUserAuthId, UserUtils.getLoginUser().getId()));
        List<Appointment> appointments = appointmentDao.selectList(new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getDoctorId, doctor.getId()));
        List<Integer> idList = appointments.stream().map(item -> {
            return item.getPatientId();
        }).distinct().collect(Collectors.toList());
        List<Patient> patients = patientDao.listMyPatient(PageUtils.getLimitCurrent(), PageUtils.getSize(),conditionVO,idList);
        pageResult.setRecordList(patients);
        //设置总数
        if (StringUtils.isNotBlank(conditionVO.getKeywords()) || Objects.nonNull(conditionVO.getSex())) {
            //当为条件查询时
            pageResult.setCount(patients.size());
        } else {
            //无条件查询
            pageResult.setCount(patientDao.selectCount(new QueryWrapper<Patient>().in("id",idList)));
        }
        return pageResult;
    }
}
